Skip to content

fix(ui): edge-to-edge mobile layout on main#421

Merged
cursor[bot] merged 9 commits into
mainfrom
cursor/loose-ends-edge-to-edge-main-470d
Jul 9, 2026
Merged

fix(ui): edge-to-edge mobile layout on main#421
cursor[bot] merged 9 commits into
mainfrom
cursor/loose-ends-edge-to-edge-main-470d

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Jul 9, 2026

Copy link
Copy Markdown
Owner

Summary

Re-applies the edge-to-edge mobile layout on current main and addresses review feedback.

Review fix (P1)

  • #main-content is the phone scroll surface (overflow-y-auto) so tall routes are not clipped
  • Hide-on-scroll uses collapse + container scroll (matches ClinicalDashboard)
  • Document viewer composer scroll-hide follows #main-content when rendered inside the shell

Follow-up

  • Mode-home children fill the scroll pane for vertical centering
  • Playwright scroll helpers target #main-content instead of window
  • Mode-home centering assertions use the visible main pane band

Verification

  • npm run format:check — pass
  • npm run verify:cheap — pass locally
Open in Web Open in Cursor 

@supabase

supabase Bot commented Jul 9, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project sjrfecxgysukkwxsowpy because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@BigSimmo
BigSimmo marked this pull request as ready for review July 9, 2026 04:01
@cursor
cursor Bot force-pushed the cursor/loose-ends-edge-to-edge-main-470d branch from 1c8bd79 to 32661eb Compare July 9, 2026 04:06

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1c8bd79ee9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/components/clinical-dashboard/global-mockup-search-shell.tsx
@cursor
cursor Bot force-pushed the cursor/loose-ends-edge-to-edge-main-470d branch from 32661eb to 97bd9f5 Compare July 9, 2026 04:10
@cursor
cursor Bot enabled auto-merge July 9, 2026 04:11
@BigSimmo
BigSimmo disabled auto-merge July 9, 2026 04:19
@cursor
cursor Bot enabled auto-merge July 9, 2026 04:23
@cursor
cursor Bot force-pushed the cursor/loose-ends-edge-to-edge-main-470d branch from d8fb310 to 45c0056 Compare July 9, 2026 04:23
cursoragent and others added 4 commits July 9, 2026 04:38
- Unify mobile shell to h-dvh flex column with --mobile-composer-reserve
- Full-bleed mode home backgrounds and edge-to-edge action cards on phone
- Top-align favourites/tools while centering other mode homes on mobile
- Resolve footer dock CSS precedence; safe-area-only mobile header gutters
- Strip inset utilities from phone footer dock markup

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
Make #main-content the phone scroll surface with overflow-y-auto so tall
routes (medication details, favourites) are not clipped by the h-dvh shell.
Wire hide-on-scroll to that container via collapse strategy, matching
ClinicalDashboard, instead of relying on document scroll.

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
- Capture descendant scroll events in GlobalMockupSearchShell so nested
  page canvases still collapse the phone search dock.
- Relax mode-home search midpoint bound for top-aligned edge-to-edge layout.
- Stabilize document viewer composer hide test with scroll spacer and explicit
  scroll events; scroll the forms results scroller and blur composer focus.

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
@cursor
cursor Bot force-pushed the cursor/loose-ends-edge-to-edge-main-470d branch from 45c0056 to 827206b Compare July 9, 2026 04:42
- Keep mode-home children filling the scroll pane for vertical centering
- Document viewer hide-on-scroll follows GlobalSearchShell main scroll
- Add scrollPrimarySurface test helper for programmatic phone scroll
- Relax mode-home centering band to the visible main pane, not full viewport

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ab450cfa-fb91-43e8-bd5c-1e3143465122

📥 Commits

Reviewing files that changed from the base of the PR and between c7120f1 and 2c0d4fa.

📒 Files selected for processing (1)
  • src/components/clinical-dashboard/global-mockup-search-shell.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/clinical-dashboard/global-mockup-search-shell.tsx

📝 Walkthrough

Summary by CodeRabbit

  • New Features / Improvements
    • Enhanced mobile search and composer behavior with updated dock/backdrop masking and more consistent compact layout spacing.
  • Bug Fixes
    • Improved hide-on-scroll behavior for the composer/header across dashboard and document viewing, including nested scroll containers.
    • Refined mobile safe-area and non-dock/compact search positioning for cleaner edge-to-edge display.
  • Tests
    • Reduced UI test flakiness by switching to more reliable element-based scrolling and updated assertions.

Walkthrough

Reworks mobile composer dock masking and scroll-hide behavior around #main-content, updates related mobile layout padding and flex classes, and adjusts Playwright helpers/tests to scroll the primary surface instead of window.

Changes

Mobile composer dock scroll & layout

Layer / File(s) Summary
Backdrop and edge CSS
src/app/globals.css
Shifts backdrop mask gradient stops and narrows mobile edge positioning rules to non-dock variants.
Search shell scroll wiring
src/components/clinical-dashboard/global-mockup-search-shell.tsx
Adds phone scroll-hide reporting, nested scroll tracking from #main-content, mobile composer reserve computation, and the reserved-space padding and CSS variable wiring in the global search shell.
Mobile dock composer sizing
src/components/clinical-dashboard/master-search-header.tsx
Changes the phone footer dock composer wrapper to a simplified full-width class list when the mobile dock is active.
Document viewer scroll container
src/components/DocumentViewer.tsx
Resolves the document viewer composer scroll container from #main-content and passes it into useHideOnScroll.
Compact mobile layout classes
src/components/ClinicalDashboard.tsx, src/components/clinical-dashboard/favourites-home-page.tsx, src/components/mode-home-template.tsx
Updates compact mobile padding and flex layout classes across the clinical dashboard, favourites home page, and mode home template wrappers.
Scroll helper and UI tests
tests/playwright-scroll.ts, tests/ui-smoke.spec.ts, tests/ui-tools.spec.ts
Adds a shared scroll helper for #main-content and updates smoke/tools tests to scroll the primary surface and assert composer visibility and centering from that container.

Estimated code review effort: 3 (Moderate) | ~25 minutes

🚥 Pre-merge checks | ✅ 10 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 70.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (10 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and matches the main UI/layout change described in the diff.
Description check ✅ Passed The description includes the required Summary and Verification sections and covers the main changes; only optional template sections are sparse.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Generated And Sensitive Files ✅ Passed PASS: Diff only touches src/tests/css files; no .env, keys, logs, caches, node_modules, build, or generated artifacts were present, and secret-pattern scan found nothing.
Verification Claims ✅ Passed Verification claims name exact commands and outcomes: npm run format:check and npm run verify:cheap both marked pass locally.
Risky Git Or Deployment Actions ✅ Passed PR changes are UI/tests only; I found no force-push, hard reset, destructive clean, branch deletion, or unsafe deploy instructions in the diff.
Supabase Project And Schema Safety ✅ Passed Diff touches only UI layout and Playwright tests; no Supabase config, migrations, env examples, or RLS/policy/schema changes appear in the PR.
Runtime And Package Manager Integrity ✅ Passed The PR only touches UI/test files; package.json, package-lock.json, .npmrc, and runtime guard scripts remain unchanged and still enforce Node 24/npm 11.
Api Route Failure Handling ✅ Passed PASS: The diff only changes UI/layout and Playwright tests; no API route, server action, RAG, or provider integration code was modified, so failure-handling rules don’t apply.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/loose-ends-edge-to-edge-main-470d
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch cursor/loose-ends-edge-to-edge-main-470d

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (4)
tests/ui-tools.spec.ts (2)

790-805: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicates the new scrollPrimarySurface helper instead of reusing it.

This test manually re-implements scrolling #main-content (setting scrollTop and dispatching a bubbling scroll event) rather than calling the shared scrollPrimarySurface helper introduced in tests/playwright-scroll.ts. Beyond duplicating logic, the manual version dispatches with bubbles: true while the helper does not — an inconsistency that can mask real differences in how the app's scroll-hide reporter is wired.

♻️ Suggested refactor
-    const scroller = page.locator("`#main-content`");
-    // Step scroll down so the shell's scroll reporter sees deliberate movement.
-    for (const offset of [40, 80, 120, 160, 200]) {
-      await scroller.evaluate((node, top) => {
-        node.scrollTop = top;
-        node.dispatchEvent(new Event("scroll", { bubbles: true }));
-      }, offset);
-    }
+    // Step scroll down so the shell's scroll reporter sees deliberate movement.
+    for (const offset of [40, 80, 120, 160, 200]) {
+      await scrollPrimarySurface(page, offset);
+    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/ui-tools.spec.ts` around lines 790 - 805, The scroll setup in the
ui-tools spec duplicates the shared scrolling logic instead of using the new
scrollPrimarySurface helper. Replace the manual `#main-content` scrollTop updates
and bubbling scroll dispatch in this test with calls to scrollPrimarySurface
from tests/playwright-scroll.ts, and keep the test aligned with the helper’s
event behavior so the scroll-hide reporter is exercised consistently.

433-444: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Redundant fallback after null assertion.

mainBox?.height ?? 820 is dead code for the happy path since expect(mainBox).not.toBeNull() on the previous line already guarantees mainBox is non-null when the test proceeds; the 820 magic number is essentially unreachable and just obscures intent.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/ui-tools.spec.ts` around lines 433 - 444, The mainBox null fallback in
the ui-tools test is redundant because the preceding assertion already
guarantees a value, so remove the dead fallback and make the intent explicit.
Update the search position checks in the same test block to use the non-null
mainBox directly after the expect(mainBox).not.toBeNull() assertion, and keep
the comparison anchored on the existing mainBox, searchBox, and headingBox
locators.
src/components/DocumentViewer.tsx (1)

1941-1958: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

DOM-ID coupling + whole-body MutationObserver for scroll-container resolution.

shellScrollContainer is resolved via getElementById("main-content") inside a MutationObserver watching document.body with { childList: true, subtree: true } for the component's entire lifetime. This works, but:

  • It couples DocumentViewer to a magic string ID owned by global-mockup-search-shell.tsx, with no compile-time contract — a rename there silently breaks scroll-hide here.
  • The observer callback fires on any DOM mutation anywhere in the app (sheets opening, image lists re-rendering, etc.), not just changes relevant to #main-content.

Since the shell already owns a mainRef/scroll-root value, consider exposing it via a small context (or prop) instead of DOM lookups, so this becomes a typed dependency rather than an implicit string-ID contract.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/DocumentViewer.tsx` around lines 1941 - 1958, The scroll
container lookup in DocumentViewer is tightly coupled to the hardcoded
"main-content" DOM id and uses a broad MutationObserver over document.body for
the component lifetime. Replace this implicit DOM query in the
shellScrollContainer/useHideOnScroll setup with a typed dependency from the
shell, such as a small context or prop backed by the shell’s mainRef/scroll-root
value, so DocumentViewer no longer depends on a magic string or whole-app
mutation watching.
src/components/clinical-dashboard/favourites-home-page.tsx (1)

20-32: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider reusing ModeHomeMain instead of duplicating its wrapper styling.

This <main> re-implements most of ModeHomeMain's classes (flex min-h-0 w-full flex-1 flex-col bg-[color:var(--background)] ... text-[color:var(--text)]) but diverges in a few subtle ways that look unintentional:

  • Uses py-4/sm:py-5 instead of the separate pt-[clamp(...)]/pb-4/sm:pt-[clamp(...)]/sm:pb-[clamp(...)] split that mode-home-template.tsx now uses (line 130).
  • Uses sm:px-4 here vs sm:px-6 in ModeHomeMain (line 130).
  • Omits items-center justify-center (intentional here, since Favourites stays top-aligned per the comment in ClinicalDashboard.tsx around line 2914-2917), but that intent isn't documented in this file.

Since both wrappers now implement the same "edge-to-edge main + inner px-4 sm:px-0 div" pattern for the same underlying reason (composer-reserve edge-to-edge layout), extending ModeHomeMain with an alignment option (e.g., align="start" | "center") and reusing it here would keep the two paths from drifting further apart as the mobile shell layout continues to evolve.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/clinical-dashboard/favourites-home-page.tsx` around lines 20 -
32, The Favourites home page is duplicating `ModeHomeMain` wrapper styling and
has already drifted in padding and alignment details. Update
`FavouritesHomePage` to reuse `ModeHomeMain` (or extend `ModeHomeMain` with an
alignment option such as start vs center) instead of hardcoding the `<main>`
classes here, and keep the inner `px-4 sm:px-0` layout. Make sure the special
top-aligned behavior for favourites is preserved explicitly through
`ModeHomeMain`, so this file only passes the needed props and `FavouritesHub`
stays unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/clinical-dashboard/global-mockup-search-shell.tsx`:
- Around line 327-340: The scroll-capture setup in GlobalMockupSearchShell only
runs once in useEffect and can miss attaching when mainRef.current is initially
null. Update the listener wiring around mainRef/onScrollCapture so it attaches
when `#main-content` becomes available, either by using a callback ref or by
making the effect rerun when the main element appears; ensure the cleanup still
removes the same capture listener.

---

Nitpick comments:
In `@src/components/clinical-dashboard/favourites-home-page.tsx`:
- Around line 20-32: The Favourites home page is duplicating `ModeHomeMain`
wrapper styling and has already drifted in padding and alignment details. Update
`FavouritesHomePage` to reuse `ModeHomeMain` (or extend `ModeHomeMain` with an
alignment option such as start vs center) instead of hardcoding the `<main>`
classes here, and keep the inner `px-4 sm:px-0` layout. Make sure the special
top-aligned behavior for favourites is preserved explicitly through
`ModeHomeMain`, so this file only passes the needed props and `FavouritesHub`
stays unchanged.

In `@src/components/DocumentViewer.tsx`:
- Around line 1941-1958: The scroll container lookup in DocumentViewer is
tightly coupled to the hardcoded "main-content" DOM id and uses a broad
MutationObserver over document.body for the component lifetime. Replace this
implicit DOM query in the shellScrollContainer/useHideOnScroll setup with a
typed dependency from the shell, such as a small context or prop backed by the
shell’s mainRef/scroll-root value, so DocumentViewer no longer depends on a
magic string or whole-app mutation watching.

In `@tests/ui-tools.spec.ts`:
- Around line 790-805: The scroll setup in the ui-tools spec duplicates the
shared scrolling logic instead of using the new scrollPrimarySurface helper.
Replace the manual `#main-content` scrollTop updates and bubbling scroll dispatch
in this test with calls to scrollPrimarySurface from tests/playwright-scroll.ts,
and keep the test aligned with the helper’s event behavior so the scroll-hide
reporter is exercised consistently.
- Around line 433-444: The mainBox null fallback in the ui-tools test is
redundant because the preceding assertion already guarantees a value, so remove
the dead fallback and make the intent explicit. Update the search position
checks in the same test block to use the non-null mainBox directly after the
expect(mainBox).not.toBeNull() assertion, and keep the comparison anchored on
the existing mainBox, searchBox, and headingBox locators.
🪄 Autofix (Beta)

✅ Autofix completed


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7a89d3f1-017b-4efd-b01c-8ee9a76af82a

📥 Commits

Reviewing files that changed from the base of the PR and between 8163549 and c7120f1.

📒 Files selected for processing (10)
  • src/app/globals.css
  • src/components/ClinicalDashboard.tsx
  • src/components/DocumentViewer.tsx
  • src/components/clinical-dashboard/favourites-home-page.tsx
  • src/components/clinical-dashboard/global-mockup-search-shell.tsx
  • src/components/clinical-dashboard/master-search-header.tsx
  • src/components/mode-home-template.tsx
  • tests/playwright-scroll.ts
  • tests/ui-smoke.spec.ts
  • tests/ui-tools.spec.ts

Comment thread src/components/clinical-dashboard/global-mockup-search-shell.tsx Outdated
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

Fixes Applied Successfully

Fixed 1 file(s) based on 1 unresolved review comment.

Files modified:

  • src/components/clinical-dashboard/global-mockup-search-shell.tsx

Commit: 3c38323ed71376011eb83dc45e98983f98569939

The changes have been pushed to the cursor/loose-ends-edge-to-edge-main-470d branch.

Time taken: 6m 57s

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

Fixes Applied Successfully

Fixed 1 file(s) based on 1 unresolved review comment.

A stacked PR containing fixes has been created.

  • Stacked PR: #432
  • Files modified:
  • src/components/clinical-dashboard/global-mockup-search-shell.tsx

Time taken: 7m 18s

Fixed 1 file(s) based on 1 unresolved review comment.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

❌ Failed to clone repository into sandbox. Please try again.

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

Fixes Applied Successfully

Fixed 1 file(s) based on 1 unresolved review comment.

Files modified:

  • src/components/clinical-dashboard/global-mockup-search-shell.tsx

Commit: cb3ed0c04f64a895ea23a4b61583785c287275e0

The changes have been pushed to the cursor/loose-ends-edge-to-edge-main-470d branch.

Time taken: 4m 2s

Fixed 1 file(s) based on 1 unresolved review comment.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
@cursor
cursor Bot merged commit 49cbd22 into main Jul 9, 2026
8 checks passed
@BigSimmo
BigSimmo deleted the cursor/loose-ends-edge-to-edge-main-470d branch July 9, 2026 11:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants